
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <uapi/linux/input.h>
#include <linux/input.h>
#include <linux/input/mt.h>

#include "multitouch.h"


static int gt1151_read_coordination(struct iic_dev *gt1151dev, 
                                    u16 reg, u8 *point)
{
    u8 ret = 0;

    ret = iic_regs16_read(gt1151dev, reg, point, 5);
    if (ret < 0)
    {
        return -1;
    }

    return 0;
}

static int gt1151_read_reg(struct iic_dev *gt1151dev, u16 reg, u8 *value)
{
    u8 ret = 0;

    ret = iic_regs16_read(gt1151dev, reg, value, 1);
    if (ret < 0)
    {
        return -1;
    }

    return 0;
}

static int gt1151_write_reg(struct iic_dev *gt1151dev, u16 reg, u8 data)
{
    u8 buf = data;

    iic_regs16_write(gt1151dev, reg, &buf, 1);
}

/* gt1151 apis */
static int gt1151_reset(struct i2c_client *client, struct iic_dev *gt1151dev)
{
    int ret = 0;

    if (gpio_is_valid(gt1151dev->rst_pin))
    {
        // 申请复位IO，默认输出低电平
        ret = devm_gpio_request_one(&client->dev,
                    gt1151dev->rst_pin, GPIOF_OUT_INIT_HIGH,
                    "gt1151 reset");
        if (ret)
        {
            return ret;
        }
        /* 复位GT1151，要严格按照GT1151时序要求 */
        gpio_set_value(gt1151dev->rst_pin, 0); /* 复位GT1151 */
        msleep(10);
        gpio_set_value(gt1151dev->rst_pin, 1); /* 停止复位GT1151 */
        msleep(10);
    }

    return 0;
}

static int gt1151_irq(struct i2c_client *client, struct iic_dev *gt1151dev)
{
    int ret = 0;

    if (gpio_is_valid(gt1151dev->irq_pin))
    {
        // 申请中断IO
        ret = devm_gpio_request_one(&client->dev,
                    gt1151dev->irq_pin, GPIOF_IN,
                    "goodix-gt1151qm irq");
        if(ret)
        {
            dev_err(&client->dev, "request GPIO%d, error %d\n", gt1151dev->irq_pin, ret);
            return ret;
        }
        printk("irq request success!\r\n");
    }

    // 申请中断，client->irq就是IO中断
    ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
                touch_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                client->name, gt1151dev);
	if(ret)
    {
        dev_err(&client->dev, "request irq faile!\n");
        return ret;
    }

    return 0;
}

static irqreturn_t touch_handler(int irq, void *dev_id)
{
    struct iic_dev *dev = dev_id;
    int x, y;
    int id = 0;
    u8 data;
    u8 gt1151_num;
    u8 gt1151_data[5];
    int ret;
    int i;

    // invalid interrut
    ret = gt1151_read_reg(dev, GT_STATUS_REG, &data);            // GT1151标志
    if (ret == -1)
    {
        printk("Unable to read PID.\n");
        return -EINVAL;
    }

    // get gt1151 points
    gt1151_num = data & 0xf;
    if(gt1151_num > 0)
    {
        for(i = 0; i < gt1151_num; i ++)                                    // 读取全部有效坐标
        {   // 读坐标
            ret = gt1151_read_coordination(dev, GT_TP1_REG + GT_TP_OFFSET * i, gt1151_data);
            id = gt1151_data[0] & 0xF;  //track Id
            x  = gt1151_data[1] | (gt1151_data[2] << 8);    // x
            y  = gt1151_data[3] | (gt1151_data[4] << 8);    // y

            input_mt_slot(dev->input, id);
            input_mt_report_slot_state(dev->input, MT_TOOL_FINGER, true); //上报按键状态
            input_report_abs(dev->input, ABS_MT_POSITION_X, x);     // 上报坐标
            input_report_abs(dev->input, ABS_MT_POSITION_Y, y);
        }
    }
    else                                                            // 无触摸-全为抬起
    {
        for(i = 0;i < MAX_SUPPORT_POINTS; i ++)
        {
            input_mt_slot(dev->input, i);
            input_mt_report_slot_state(dev->input, MT_TOOL_FINGER, false);
        }
    }

    input_mt_report_pointer_emulation(dev->input, true);
    input_sync(dev->input);

    /* 清除中断标志位 */
    gt1151_write_reg(dev, GT_STATUS_REG, 0x0);

    return IRQ_HANDLED;
}

static int gt1151_init(struct i2c_client *client, struct iic_dev *gt1151dev)
{
    /* INT输入模式，拉高 */
    gpio_set_value(gt1151dev->irq_pin, 0);    /* 拉低INT引脚 */
    msleep(50);
    gpio_direction_input(gt1151dev->irq_pin); /* INT引脚设置为输入 */
    gpio_set_value(gt1151dev->irq_pin, 1);    /* 拉高INT引脚 */

    /* 初始化GT1151 */
    gt1151_write_reg(gt1151dev, GT_CTRL_REG, 0x02); /* 软复位 */
    mdelay(100);
    gt1151_write_reg(gt1151dev, GT_CTRL_REG, 0x00); /* 停止软复位 */
    mdelay(100);

#if 0
    u16 data = 0;
    u16 temp = 0;

    temp = gt1151_read_reg(gt1151dev, GT_PID_H_REG);
    if (temp == -1)
    {
        printk("Unable to read PID high bits.\n");
    }
    temp = temp << 8;
    data = gt1151_read_reg(gt1151dev, GT_PID_L_REG);
    if (data == -1)
    {
        printk("Unable to read PID low bits.\n");
    }
    data = temp + data;
    printk("productID = %#x\n", data);

    data = gt1151_read_reg(gt1151dev, GT_STATUS_REG);
    printk("status = %#x\n", data);
#endif

    return 0;
}

static int gt1151_input_register(struct i2c_client *client, struct iic_dev *gt1151dev)
{
    int ret = 0;

    /* input设备注册 */
	gt1151dev->input = devm_input_allocate_device(&client->dev);
	if (!gt1151dev->input) {
        printk("can't allocate input device\n");
        return -EINVAL;
	}
	gt1151dev->input->name = client->name;
	gt1151dev->input->id.bustype = BUS_I2C;
	gt1151dev->input->dev.parent = &client->dev;
 
	__set_bit(EV_KEY, gt1151dev->input->evbit);
	__set_bit(EV_ABS, gt1151dev->input->evbit);
	__set_bit(BTN_TOUCH, gt1151dev->input->keybit);
 
	input_set_abs_params(gt1151dev->input, ABS_X, 0, TOUCH_HORIZENT_PIX, 0, 0);
	input_set_abs_params(gt1151dev->input, ABS_Y, 0, TOUCH_VERTICAL_PIX, 0, 0);
	input_set_abs_params(gt1151dev->input, ABS_MT_POSITION_X,0, TOUCH_HORIZENT_PIX, 0, 0);
	input_set_abs_params(gt1151dev->input, ABS_MT_POSITION_Y,0, TOUCH_VERTICAL_PIX, 0, 0);	     
	ret = input_mt_init_slots(gt1151dev->input, MAX_SUPPORT_POINTS, 0);
	if (ret) 
    {
        printk("can't allocate input device\n");
        return -EINVAL;
	}
 
	ret = input_register_device(gt1151dev->input);

    return 0;
}

/* 字符设备读写，用于上层调用 */
static int gt1151_open(struct inode *inode, struct file *filp)
{
#ifdef ATOMIC
    if (!atomic_dec_and_test(&gt1151dev.lock))
    {
        atomic_inc(&gt1151dev.lock);
        return -EBUSY;
    }
#endif

#ifdef TIMER
    gt1151dev.period = 1000;
#endif

    filp->private_data = &gt1151dev; /* 设置私有数据 */
    return 0;
}

static ssize_t gt1151_write(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    return 0;
}

static int gt1151_release(struct inode *inode, struct file *filp)
{
    /*struct iic_dev *dev = filp->private_data;*/
#ifdef ATOMIC
    atomic_inc(&dev->lock);
#endif

    return 0;
}

static struct file_operations gt1151dev_fops = {
    .owner = THIS_MODULE,
    .open = gt1151_open,
    .write = gt1151_write,
    .release = gt1151_release,
};

/* i2c设备的具体功能 */
static int gt1151_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    printk(KERN_EMERG "\t match successed, initial multi gt1151 device\r\n");

    /* 注册字符设备驱动 */
    /* 1、创建设备号 */
    if (gt1151dev.major)
    {
        gt1151dev.devid = MKDEV(gt1151dev.major, 0);
        register_chrdev_region(gt1151dev.devid, DEV_CNT, CHRDEV_NAME);
    }
    else
    {
        alloc_chrdev_region(&gt1151dev.devid, 0, DEV_CNT, CHRDEV_NAME); /* 申请设备号 */
        gt1151dev.major = MAJOR(gt1151dev.devid); /* 获取主设备号 */
        gt1151dev.minor = MINOR(gt1151dev.devid); /* 获取次设备号 */
    }

    printk("gt1151dev major=%d,minor=%d\r\n",gt1151dev.major, gt1151dev.minor);

    /* 2、初始化 cdev */
    gt1151dev.cdev.owner = THIS_MODULE;
    cdev_init(&gt1151dev.cdev, &gt1151dev_fops);

    /* 3、添加一个 cdev */
    cdev_add(&gt1151dev.cdev, gt1151dev.devid, DEV_CNT);

    /* 4、创建类 */
    gt1151dev.class = class_create(THIS_MODULE, CHRDEV_NAME);
    if (IS_ERR(gt1151dev.class))
    {
        return PTR_ERR(gt1151dev.class);
    }

    /* 5、创建设备 */
    gt1151dev.device = device_create(gt1151dev.class, NULL, gt1151dev.devid, NULL, CHRDEV_NAME);
    if (IS_ERR(gt1151dev.device))
    {
        return PTR_ERR(gt1151dev.device);
    }

    /* 1, 获取设备树中 cs片选信号 */
    gt1151dev.node = of_find_node_by_path("/soc/aips-bus@02100000/i2c@021a0000/gt1151qm@14");
    if(gt1151dev.node == NULL) 
    {
        printk("multi gt1151 node not find!\r\n");
        return -EINVAL;
    }

    /* 2、 获取设备树中的 gpio属性，得到 中断和复位所使用的 GPIO编号 */
    gt1151dev.irq_pin = of_get_named_gpio(gt1151dev.node, "irq-gpios", 0);
    if(gt1151dev.irq_pin < 0) 
    {
        printk("can't get interrupt pin\n");
        return -EINVAL;
    }

    gt1151dev.rst_pin = of_get_named_gpio(gt1151dev.node, "reset-gpios", 0);
    if(gt1151dev.rst_pin < 0) 
    {
        printk("can't get reset pin\n");
        return -EINVAL;
    }

    gt1151dev.private_data = client;

    gt1151_reset(client, &gt1151dev);       // 注册复位，irq输入模式
    gt1151_init(client, &gt1151dev);        // 初始化，复位gt1151
    gt1151_input_register(client, &gt1151dev);  // 注册input子系统

    gt1151_irq(client, &gt1151dev);

    return 0;
}

static int gt1151_remove(struct platform_device *dev)
{
    /* 注销字符设备 */
    cdev_del(&gt1151dev.cdev);/* 删除 cdev */
    unregister_chrdev_region(gt1151dev.devid, DEV_CNT);

    device_destroy(gt1151dev.class, gt1151dev.devid);
    class_destroy(gt1151dev.class);

    return 0;
}

static int __init iic_gt1151_init(void)
{
    int ret;
    printk("gt1151 drivers init\r\n");

    ret = i2c_add_driver(&gt1151_driver);

    return ret;
}

static void __exit iic_gt1151_exit(void)
{
    printk("gt1151 drivers exit\r\n");

    i2c_del_driver(&gt1151_driver);
}

module_init(iic_gt1151_init);
module_exit(iic_gt1151_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xue");


